package com.zj.osm.utils;

/**
 * <pre>
 *     author : luhenchang
 *     e-mail : 1276998208@qq.com
 *     time   : 2020/01/13
 *     desc   : 版权所有
 *     version: 1.0
 * </pre>
 */
public class GaussKrugerProjection {
    /**
     *
     * @param B 纬度
     * @param L 经度
     * @param degree //
     * @param withBand 默认=false
     * @return
     */
    public static Tuple  GetXY(double B, double L, double degree, Boolean withBand) {
        double[] xy = {0, 0};

        double a = 6378137;//椭球长半轴
        double b = 6356752.3142451795;//椭球短半轴
        double e = 0.081819190842621;//第一偏心率
        double eC = 0.0820944379496957;//第二偏心率

        double L0 = 0;//中央子午线经度
        int n = 0;//带号
        if (degree == 6) {
            //6度
            n = (int) (Math.round((L + degree / 2) / degree));
            L0 = degree * n - degree / 2;
        } else {
            //3度
            n = (int) Math.round(L / degree);
            L0 = degree * n;
        }

        //开始计算
        double radB = B * Math.PI / 180;//纬度(弧度)
        double radL = L * Math.PI / 180;//经度(弧度)
        double deltaL = (L - L0) * Math.PI / 180;//经度差(弧度)
        double N = a * a / b / Math.sqrt(1 + eC * eC * Math.cos(radB) * Math.cos(radB));
        double C1 = 1.0 + 3.0 / 4 * e * e + 45.0 / 64 * Math.pow(e, 4) + 175.0 / 256 * Math.pow(e, 6) + 11025.0 / 16384 * Math.pow(e, 8);
        double C2 = 3.0 / 4 * e * e + 15.0 / 16 * Math.pow(e, 4) + 525.0 / 512 * Math.pow(e, 6) + 2205.0 / 2048 * Math.pow(e, 8);
        double C3 = 15.0 / 64 * Math.pow(e, 4) + 105.0 / 256 * Math.pow(e, 6) + 2205.0 / 4096 * Math.pow(e, 8);
        double C4 = 35.0 / 512 * Math.pow(e, 6) + 315.0 / 2048 * Math.pow(e, 8);
        double C5 = 315.0 / 131072 * Math.pow(e, 8);
        double t = Math.tan(radB);
        double eta = eC * Math.cos(radB);
        double X = a * (1 - e * e) * (C1 * radB - C2 * Math.sin(2 * radB) / 2 + C3 * Math.sin(4 * radB) / 4 - C4 * Math.sin(6 * radB) / 6 + C5 * Math.sin(8 * radB));

        xy[0] = X + N * Math.sin(radB) * Math.cos(radB) * Math.pow(deltaL, 2) * (1 + Math.pow(deltaL * Math.cos(radB), 2) * (5 - t * t + 9 * eta * eta + 4 * Math.pow(eta, 4)) / 12 + Math.pow(deltaL * Math.cos(radB), 4) * (61 - 58 * t * t + Math.pow(t, 4)) / 360) / 2;
        xy[1] = N * deltaL * Math.cos(radB) * (1 + Math.pow(deltaL * Math.cos(radB), 2) * (1 - t * t + eta * eta) / 6 + Math.pow(deltaL * Math.cos(radB), 4) * (5 - 18 * t * t + Math.pow(t, 4) - 14 * eta * eta - 58 * eta * eta * t * t) / 120) + 500000;// +n * 1000000;

        return new Tuple(xy[0], xy[1]);
    }

    /*public Tuple GetBL(double mX, double mY, double degree, Boolean withBand) {
        double[] xy = {0, 0};

        double a = 6378137;//椭球长半轴
        double b = 6356752.3142451795;//椭球短半轴
        double e = 0.081819190842621;//第一偏心率
        double eC = 0.0820944379496957;//第二偏心率

        double L0 = 0;//中央子午线经度
        int n = 0;//带号
        if (degree == 6) {
            //6度
            n = (int) (Math.round((L + degree / 2) / degree));
            L0 = degree * n - degree / 2;
        } else {
            //3度
            n = (int) Math.round(L / degree);
            L0 = degree * n;
        }

        //开始计算
        mX=radB/ Math.PI / 180;
        //double radL = L * Math.PI / 180;//经度(弧度)
        double deltaL = (L - L0) * Math.PI / 180;//经度差(弧度)
        double N = a * a / b / Math.sqrt(1 + eC * eC * Math.cos(radB) * Math.cos(radB));
        double C1 = 1.0 + 3.0 / 4 * e * e + 45.0 / 64 * Math.pow(e, 4) + 175.0 / 256 * Math.pow(e, 6) + 11025.0 / 16384 * Math.pow(e, 8);
        double C2 = 3.0 / 4 * e * e + 15.0 / 16 * Math.pow(e, 4) + 525.0 / 512 * Math.pow(e, 6) + 2205.0 / 2048 * Math.pow(e, 8);
        double C3 = 15.0 / 64 * Math.pow(e, 4) + 105.0 / 256 * Math.pow(e, 6) + 2205.0 / 4096 * Math.pow(e, 8);
        double C4 = 35.0 / 512 * Math.pow(e, 6) + 315.0 / 2048 * Math.pow(e, 8);
        double C5 = 315.0 / 131072 * Math.pow(e, 8);
        double t = Math.tan(radB);
        double eta = eC * Math.cos(radB);
        double X = a * (1 - e * e) * (C1 * radB - C2 * Math.sin(2 * radB) / 2 + C3 * Math.sin(4 * radB) / 4 - C4 * Math.sin(6 * radB) / 6 + C5 * Math.sin(8 * radB));

        mX= X + N * Math.sin(radB) * Math.cos(radB) * Math.pow(deltaL, 2) * (1 + Math.pow(deltaL * Math.cos(radB), 2) * (5 - t * t + 9 * eta * eta + 4 * Math.pow(eta, 4)) / 12 + Math.pow(deltaL * Math.cos(radB), 4) * (61 - 58 * t * t + Math.pow(t, 4)) / 360) / 2;
        mY = N * deltaL * Math.cos(radB) * (1 + Math.pow(deltaL * Math.cos(radB), 2) * (1 - t * t + eta * eta) / 6 + Math.pow(deltaL * Math.cos(radB), 4) * (5 - 18 * t * t + Math.pow(t, 4) - 14 * eta * eta - 58 * eta * eta * t * t) / 120) + 500000;// +n * 1000000;

        return new Tuple(xy[0], xy[1]);
    }*/

    public static class  Tuple {
        Double B;
        Double L;

        public Tuple(Double b, Double l) {
            B = b;
            L = l;
        }

        public Double getB() {
            return B;
        }

        public void setB(Double b) {
            B = b;
        }

        public Double getL() {
            return L;
        }

        public void setL(Double l) {
            L = l;
        }

        @Override
        public String toString() {
            return "Tuple{" +
                    "B=" + B +
                    ", L=" + L +
                    '}';
        }
    }

}
